#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <sys/msg.h>

#define BUFSIZE 128

struct msg_buf {    //自定义消息结构体
    long type;
    char msg[BUFSIZE];
};

int main(int argc, char *argv[])
{
    key_t key;
    int msgid;
    struct msg_buf msg_snd, msg_rcv;
    struct msqid_ds msg_info;
    char *ptr = "hello world";
    int msgrcv_return;      //定义变量用于保存msgrcv()的返回值，表示读取的消息字节数
    int reval;
    memset(&msg_snd, '\0', sizeof(struct msg_buf));
    memset(&msg_rcv, '\0', sizeof(struct msg_buf));
    msg_rcv.type = 1;       //消息类型
    msg_snd.type = 1;
    memcpy(msg_snd.msg, ptr, strlen(ptr));

    //创建key值
    if ((key = ftok(".", 'A')) == -1) {
        perror("ftok");
        exit(EXIT_FAILURE);
    }

    //创建消息队列
    if ((msgid = msgget(key, 0600 | IPC_CREAT)) == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    //获取消息队列属性（创建消息队列后）
    if ((reval = msgctl(msgid, IPC_STAT, &msg_info)) == -1) {
        printf("get message information error\n");
        perror("msgctl");
        exit(EXIT_FAILURE);
    }

    printf("current number of bytes on queue is %d\n", msg_info.msg_cbytes);
    printf("number of messages in queue is %d\n", msg_info.msg_qnum);
    printf("max number of bytes on queue is %d\n", msg_info.msg_qbytes);
    printf("pid of last msgsnd is %d\n", msg_info.msg_lspid);
    printf("pid of last msgrcv is %d\n", msg_info.msg_lrpid);
    printf("msg uid is %d\n", msg_info.msg_perm.uid);
    printf("msg gid is %d\n", msg_info.msg_perm.gid);
    printf("\n");

    //发送消息
    printf("msgsnd return = %d\n", msgsnd(msgid, (void *)&msg_snd, strlen(msg_snd.msg), 0));
    //获取消息队列属性并打印（发生消息后）
    if ((reval = msgctl(msgid, IPC_STAT, &msg_info)) == -1) {
        printf("get message information error\n");
        perror("msgctl");
        exit(EXIT_FAILURE);
    }

    printf("current number of bytes on queue is %d\n", msg_info.msg_cbytes);
    printf("number of messages in queue is %d\n", msg_info.msg_qnum);
    printf("max number of bytes on queue is %d\n", msg_info.msg_qbytes);
    printf("pid of last msgsnd is %d\n", msg_info.msg_lspid);
    printf("pid of last msgrcv is %d\n", msg_info.msg_lrpid);
    printf("msg uid is %d\n", msg_info.msg_perm.uid);
    printf("msg gid is %d\n", msg_info.msg_perm.gid);
    printf("\n");

    //接受消息      第四个参数为1，表示返回类型为mtype(即msg_rcv.type)的第一个消息
    msgrcv_return = msgrcv(msgid, (void *)&msg_rcv, BUFSIZE, 1, 0);
    printf("msgrcv_return = %d\n", msgrcv_return);
    //获取消息队列属性并打印（接受消息后）
    if ((reval = msgctl(msgid, IPC_STAT, &msg_info)) == -1) {
        printf("get message information error\n");
        perror("msgctl");
        exit(EXIT_FAILURE);
    }

    printf("current number of bytes on queue is %d\n", msg_info.msg_cbytes);
    printf("number of messages in queue is %d\n", msg_info.msg_qnum);
    printf("max number of bytes on queue is %d\n", msg_info.msg_qbytes);
    printf("pid of last msgsnd is %d\n", msg_info.msg_lspid);
    printf("pid of last msgrcv is %d\n", msg_info.msg_lrpid);
    printf("msg uid is %d\n", msg_info.msg_perm.uid);
    printf("msg gid is %d\n", msg_info.msg_perm.gid);
    printf("\n");

    //打印接收到的消息文本
    printf("rev msg:%s\n", msg_rcv.msg);
    //删除消息队列
    printf("msgctl_return = %d\n", msgctl(msgid, IPC_RMID, 0));
}